#ifndef __WS_IOCTL_HOST_H_
#define __WS_IOCTL_HOST_H_

#include "Private.h"
#include "thread_pool.h"
#include "UMMsgMap.h"
#include "Directive.h"
#include <map>
#include <set>
#include <utility>
#include <mutex>
#include <chrono>
struct lws_protocols;

namespace sdk {
namespace msg {
using UserOutData = std::pair<WsUserSession *, std::string>;
using UserOutDataQueue = aw::threadsafe_queue<UserOutData>;
using steady_time_point = aw::steady_time_point;
using steady_clock = aw::steady_clock;

struct ModulesProxy {
public:
    ModulesProxy();
    ~ModulesProxy();
    void ioctlWorkThread();
    void scheduleThread();
    template <typename FunctionType>
    std::future<typename std::result_of<FunctionType()>::type> submit(FunctionType &&f, steady_time_point time = steady_clock::now())
    {
        return m_thPool.submit(std::move(f), time);
    }

    void addSession(WsUserSession *);
    void delSession(WsUserSession *);
    bool hasSession(WsUserSession *);
    size_t sessionSize() const;
    bool sessionIsEmpty() const;
    bool clearUserOutData();
    bool popUserOutData(UserOutData &data);
    void pushUserOutData(UserOutData &data);
    void pushUserOutData(const WsSession &ses, std::string &jsonData);
    bool isStopped() const;
    bool doDirective(std::shared_ptr<Directive> dir, WsSession session);
    bool doDirective(std::shared_ptr<std::string> bufptr, std::optional<steady_time_point> endtime = {}, uint32_t retryIdx = 0);
    std::shared_ptr<Directive> getDirectiveOnModuleId(EJsonMsgNamesp, EJsonMsgName)const;
    static bool timerDirective(ModulesProxy *proxy, std::shared_ptr<std::string> bufptr, std::optional<steady_time_point> endtime, uint32_t retryIdx);

private:
    int m_msqid = -1;
    std::set<WsUserSession *> m_sessions{};
    UserOutDataQueue m_dsqueue;
    std::atomic_bool m_stop = false;
    std::thread m_moduleThread;
    aw::thread_pool m_thPool = aw::thread_pool(1);

    mutable std::mutex m_mut;
    std::map<long, std::pair<std::shared_ptr<Directive>, WsSession>> m_msgSess;
    std::map<std::pair<EJsonMsgNamesp, EJsonMsgName>, std::shared_ptr<Directive>> m_msgDirMap;
    std::set<long> m_waitedModIds;
};

} // namespace msg
} // namespace sdk

#endif // __WS_IOCTL_HOST_H_